import Base from './base.js'
import Gan from './gan.js'
import Zhi from './zhi.js'
import Xun from './xun.js'
import Nayin from './nayin.js'

import dictionary from './dictionary.js'


// 黄道列表
const huangdaoList = ['青龙', '明堂', '天刑', '朱雀', '金匮', '天德', '白虎', '玉堂', '天牢', '玄武', '司命', '勾陈']
// 上面的黄道列表中，那些为黄道true，那些为黑道false
const huangHeiList = [true, true, false, false, true, true, false, true, false, false, true, false]

// 干支类不继承于Base类
// 这个干支类的执行效率很差,使用时要注意
class Ganzhi extends Base {
  constructor (gan = 0, zhi = 0, xun = 0, options = {}) {
    super(options)
    
    // 内部创建 干 支 旬 子对象时所用的配置
    this.initChildOptions()
    // 初始化属性
    this.initGanzhi(gan, zhi, xun)
  }
  
  initGanzhi (gan = 0, zhi = 0, xun = 0) {
    this.types.push('Ganzhi')
    
    // console.log(gan, zhi)
    this.gan = new Gan(gan, this.childGanOptions)
    this.zhi = new Zhi(zhi, this.childZhiOptions)
    this.xun = new Xun(xun, this.childXunOptions)
    
    if (this.gan.index !== null && this.zhi.index !== null) {
      // 先尝试用干支初始化旬
      this.getXun()
    }
    else if (this.gan.index !== null && this.xun.index !== null) {
      // 然后尝试用干和旬初始化支
      this.getZhi()
    }
    else {
      // 然后尝试用支和旬初始化干
      this.getGan()
    }
    
    // 获取索引值和名称
    this.getGanzhi()
    
    // 解析干支中更复杂的内容
    this.initExtras()
  }
  
  // 生成子元素的设定初始化
  initChildOptions () {
    // 干的详细设定
    this.childGanOptions = {
      description: this.description + dictionary.GAN
    }
    this.childZhiOptions = {
      description: this.description + dictionary.ZHI
    }
    this.childXunOptions = {
      description: this.description + dictionary.XUN
    }
    // 这里parent到时候再指定,因为this.zhi可能会改变指向,造成BUG
    this.childHiddenGanOptions = {
      description: this.description + dictionary.ZHI + dictionary.HIDDENGAN
    }
  }
  
  // 解析干支中更复杂的内容
  initExtras () {
    if (this.options.hiddenGanEnabled) {
      // 解析藏干
      this.initHiddenGan()
    }
    if (this.options.hasOwnProperty('huangdaoGanIndex')) {
      // 解析黄道
      this.initHuangdao(this.options.huangdaoGanIndex)
    }
  }
  
  // 根据干支,获取旬
  getXun () {
    let tempGan = new Gan(this.gan.index)
    let tempZhi = new Zhi(this.zhi.index)
    tempZhi.prev(tempGan.index)
    tempGan.prev(tempGan.index)
    const ganzhi = tempGan.name + tempZhi.name
    this.xun = new Xun(ganzhi, this.childXunOptions)
  }
  
  // 根据干和旬,获取支
  getZhi () {
    let xunZhi = new Zhi(this.xun.name[1])
    xunZhi.next(this.gan.index)
    this.zhi = new Zhi(xunZhi.index, this.childZhiOptions)
  }
  
  // 根据支和旬,获取干
  getGan () {
    const zhiLen = Zhi.zhiList.length
    const xunZhi = new Zhi(this.xun.name[1])
    const delta = (this.zhi.index + zhiLen - xunZhi.index) % zhiLen
    this.gan = new Gan(this.xun.name[0], this.childGanOptions)
    this.gan.next(delta)
  }
  
  // 获取索引值和名称
  getGanzhi () {
    if (this.gan.index !== null && this.zhi.index !== null && this.xun.index !== null) {
      this.index = this.xun.index * Gan.ganList.length + this.gan.index
      this.name = this.gan.name + this.zhi.name
      this.nayin = new Nayin(Math.floor(this.index / 2), {
        description: this.description + dictionary.NAYIN
      })
    }
    else {
      this.enabled = false
    }
  }
  
  // 解析第一级地支藏干
  initHiddenGan () {
    if (this.zhi.hiddenGans.length > 0) {
      // 避免重复解析
      return
    }
    
    let hiddenGans = []
    const hiddenGanNames = this.zhi.hiddenGansText
    const len = hiddenGanNames.length
    for (let i = 0; i < len; i++) {
      const ganName = hiddenGanNames[i]
      const hiddenGan = new Gan(ganName, this.childHiddenGanOptions)
      hiddenGans.push(hiddenGan)
    }
    this.zhi.hiddenGans = hiddenGans
  }
  
  /* 
    解析黄道，根据月支判断日的黄黑道，或者根据日支判断时的黄黑道，prevZhiIndex就是前一个地支对象的索引值
    寅申须加子,
    卯酉却居寅,
    辰戌龙位上,
    巳亥午上存,
    子午临申他,
    丑未戌相寻。
  */
  initHuangdao (prevZhiIndex) {
    // 根据 子午临申地 确定的初始位置
    const POS_INIT = 8
    
    const zhiLen = Zhi.zhiList.length
    const offset = prevZhiIndex % (zhiLen / 2)
    // 青龙的位置
    const start = (POS_INIT + 2 * offset) % zhiLen
    
    const huangdao = this.zhi.index >= start ?
      this.zhi.index - start :
      Zhi.zhiList.length - start + this.zhi.index
    
    this.huangdao = {
      index: huangdao,
      name: huangdaoList[huangdao],
      // 是否为黄道，false为黑道
      isHuangdao: huangHeiList[huangdao]
    }
  }
  
  // 获取下一个干支
  next (offset = 1) {
    const nextGan = this.gan.nextIndex(offset)
    const nextZhi = this.zhi.nextIndex(offset)
    this.initGanzhi(nextGan, nextZhi)
  }
  
  // 获取上一个干支
  prev (offset = 1) {
    const prevGan = this.gan.prevIndex(offset)
    const prevZhi = this.zhi.prevIndex(offset)
    this.initGanzhi(prevGan, prevZhi)
  }
}

Object.assign(Ganzhi, {  })

export default Ganzhi